package visam.core;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;

public class Command {
    private char[]     buffer;
    private int        gapstart  = 0;
    private int        gapend    = 0;
    private int        gapsize   = 10;
    private int        point     = 0;
    private boolean    colonmode = false;
    private boolean    visible   = false;
    private BlinkTimer bt;
    
    public Command() {
        buffer = new char[gapsize];
        gapend = gapstart + gapsize;
        Thread t = new Thread(bt);
        t.start();
    }
    
    public void moveCharLeft() {
        if (point == 0) setPoint(point - 1);
    }
    
    public void moveCharRight() {
        if (point == buffer.length) setPoint(point + 1);
    }
    
    public void deleteNext() {
        gapend += 1;
    }
    
    public void deletePrevious() {
        gapstart -= 1;
    }
    
    protected void setPoint(int input) {
        point = input;
        if (point < gapstart) {
            System.arraycopy(buffer, point, buffer, point + (gapend - gapstart), gapstart - point);
            gapend = point + (gapend - gapstart);
            gapstart = point;
        }
        else if (point > gapend) {
            System.arraycopy(buffer, gapend, buffer, gapstart, point - gapend);
            gapstart += point - gapend;
            gapend = point;
        }
        else {
            System.arraycopy(buffer, gapend, buffer, gapstart, point - gapstart);
            gapend = point + (gapend - gapstart);
            gapstart = point;
        }
        
        resetGap();
    }
    
    protected void resetGap() {
        for (int i = gapstart; i <= gapend; i++) {
            buffer[i] = 0;
        }
    }
    
    public void insert(char c) {
        if (c != 0) {
            System.out.println("inserting :" + String.valueOf((int)c));
            if ((gapend - gapstart) == 1) expandBuffer(gapsize);
            buffer[gapstart++] = c;
        }
    }
    
    public void expandBuffer(int size) {
        char[] tmp = buffer;
        int oldlen = tmp.length;
        buffer = new char[oldlen + size + 1];
        System.arraycopy(tmp, 0, buffer, 0, gapstart);
        System.arraycopy(tmp, gapend, buffer, gapstart + size, oldlen - gapend);
        gapend = gapstart + size;
    }
    
    public void draw(GC gc, Rectangle rect) {
        String line = getText();
        gc.drawText(line, rect.x, rect.y);
        if (colonMode() && visible) {
            String tmp = new String(buffer, 0, gapstart);
            Point p = gc.textExtent(tmp);
            gc.drawRectangle(p.x, rect.y, 1, rect.height);
        }
    }
    
    private String getText() {
        char[] tmp = new char[buffer.length - (gapend - gapstart)];
        System.arraycopy(buffer, 0, tmp, 0, gapstart);
        System.arraycopy(buffer, gapend, tmp, gapstart, buffer.length - gapend);
        return new String(tmp, 0, tmp.length);
    }
    
    @Override
    public String toString() {
        return new String(buffer, 0, buffer.length);
    }
    
    public void setColonMode() {
        colonmode = true;
    }
    
    public void unsetColonMode() {
        colonmode = false;
    }
    
    public boolean colonMode() {
        return colonmode;
    }
    
    public void getRange(String cmd, int start, int end) {
        
    }
    
    public void process(Text text) {
        String cmd = new String(buffer, 0, buffer.length);
        switch (cmd.charAt(0)) {
            case ':' :
                {
                    String[] commands = cmd.split(" ");
                    int index = 1;
                    int start = 0;
                    int end = 0;
                    
                    if (commands[0].charAt(index) != '.') if (Character.isDigit(commands[0].charAt(index))) {
                        while (Character.isDigit(commands[0].charAt(index))) {
                            start = start * 10 + (int)commands[0].charAt(index++);
                        }
                        if (start == 0) start = text.getLine();
                    }
                    else
                        start = 1;
                    if (commands[0].charAt(index) == ',') {
                        index++;
                        if (commands[0].charAt(index) != '$') {
                            while (Character.isDigit(commands[0].charAt(index))) {
                                end = end * 10 + (int)commands[0].charAt(index++);
                            }
                        }
                        else
                            end = text.getMaxLineCount();
                    }
                    else
                        end = text.getLine();
                    switch (commands[0].charAt(index)) {
                        case 's' :
                            {
                                String[] strs = commands[0].substring(index + 1).split("/");
                                text.substitute(start, end, strs[0], strs[1], strs[2]);
                            }
                            break;
                    }
                    {
                        switch (commands[0].charAt(1)) {
                            case 'w' :
                                {
                                    if (commands.length > 1) {
                                        String tmp = commands[1].trim();
                                        try {
                                            text.saveAs(tmp);
                                        }
                                        catch (IOException e) {
                                            // TODO Auto-generated catch block
                                            e.printStackTrace();
                                        }
                                    }
                                }
                                break;
                            case 'e' :
                                {
                                    try {
                                        String tmp = cmd.substring(3);
                                        tmp = tmp.trim();
                                        // text = new TextBuffer(tmp, 10);
                                        text.open(tmp);
                                    }
                                    catch (FileNotFoundException e) {
                                        // TODO Auto-generated catch block
                                        e.printStackTrace();
                                    }
                                    catch (IOException e) {
                                        // TODO Auto-generated catch block
                                        
                                        e.printStackTrace();
                                    }
                                }
                                break;
                            case 'r' :
                                {
                                    String tmp = cmd.substring(1).trim();
                                    File file = new File(tmp);
                                    buffer = new char[(int)file.length()];
                                }
                                break;
                            case 'q' :
                                System.exit(0);
                                break;
                            case 's' :
                                break;
                        }
                    }
                }
                break;
            case '/' :
                {
                    // Regex search
                    text.doRegExSearch(cmd.substring(1).trim());
                }
                break;
            case '%' :
                break;
            default :
                break;
        }
    }
    
    public void handle(KeyEvent kevent) {
        switch (kevent.keyCode) {
            case SWT.ARROW_LEFT :
                this.moveCharLeft();
                break;
            case SWT.ARROW_RIGHT :
                this.moveCharRight();
                break;
            case SWT.BS :
                this.deletePrevious();
                break;
            case SWT.DEL :
                this.deleteNext();
                break;
            default :
                this.insert(kevent.character);
                break;
        }
    }
    
    private class BlinkTimer implements Runnable {
        
        @Override
        public void run() {
            // TODO Auto-generated method stub
            while (true) {
                try {
                    Thread.sleep(500);
                }
                catch (Exception e) {
                    // 
                }
                visible = !visible;
            }
        }
        
    }
    
}
